home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 359_11 / patch5.000 / GO32 / CONTROL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-11  |  12.1 KB  |  530 lines

  1. /* This is file CONTROL.C */
  2. /*
  3. ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  16. /* History:87,1 */
  17. #include <dos.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include <sys/stat.h>
  22. #include <string.h>
  23.  
  24. #include "build.h"
  25. #include "types.h"
  26. #include "gdt.h"
  27. #include "idt.h"
  28. #include "tss.h"
  29. #include "valloc.h"
  30. #include "utils.h"
  31. #include "syms.h"
  32. #include "graphics.h"
  33. #include "mono.h"
  34. #include "vcpi.h"
  35.  
  36. TSS *tss_ptr;
  37. int debug_mode = 0;
  38. int self_contained;
  39. long header_offset = 0;
  40. int use_ansi=0;
  41. int use_mono=0;
  42. int redir_1_mono=0;
  43. int redir_2_mono=0;
  44. int redir_2_1=0;
  45. int redir_1_2=0;
  46.  
  47. static int old_video_mode;
  48.  
  49. int16 ems_handle=0;        /*  Get EMS Handle  */
  50. word16 vcpi_installed = 0;    /*  VCPI Installed Flag  */
  51.  
  52. extern near go32();
  53. extern near go_real_mode();
  54. extern void vcpi_flush();    /*  VCPI Memory All Cleared  */
  55.  
  56. extern int was_exception;
  57. extern near ivec0(), ivec1(), ivec7(), ivec75();
  58. extern near interrupt_common(), page_fault();
  59. extern near test();
  60.  
  61. extern word32 far *pd;
  62.  
  63. fillgdt(int sel, word32 limit, word32 base, word8 type, int G)
  64. {
  65.   GDT_S *g;
  66.   g = gdt+sel;
  67.   if (G & 2)
  68.     limit = limit >> 12;
  69.   g->lim0 = limit & 0xffff;
  70.   g->lim1 = (limit>>16) & 0x0f;
  71.   g->base0 = base & 0xffff;
  72.   g->base1 = (base>>16) & 0xff;
  73.   g->base2 = (base>>24) & 0xff;
  74.   g->stype = type;
  75.   g->lim1 |= G * 0x40;
  76. }
  77.  
  78. word32 ptr2linear(void far *ptr)
  79. {
  80.   return (word32)FP_SEG(ptr) * 16L + (word32)FP_OFF(ptr);
  81. }
  82.  
  83. setup_tss(TSS *t, int (*eip)())
  84. {
  85.   memset(t, 0, sizeof(TSS));
  86.   t->tss_cs = g_rcode*8;
  87.   t->tss_eip = (long)FP_OFF(eip);
  88.   t->tss_ss = g_rdata*8;
  89.   t->tss_esp = (long)FP_OFF(t->tss_stack);
  90.   t->tss_ds = g_rdata*8;
  91.   t->tss_es = g_rdata*8;
  92.   t->tss_fs = g_rdata*8;
  93.   t->tss_gs = g_rdata*8;
  94.   t->tss_eflags = 0x0200;
  95.   t->tss_iomap = 0xffff; /* no map */
  96. }
  97.  
  98. exit_func()
  99. {
  100.   int i;
  101.   dalloc_uninit();
  102.   uninit_controllers();
  103.   xms_free();
  104.   if ((ems_handle)&&(ems_handle != -1))
  105.     ems_free(ems_handle);    /*  Deallocated EMS Page    */
  106.   if (vcpi_installed)
  107.     vcpi_flush();        /*  Deallocated VCPI Pages  */
  108.  
  109. #if TOPLINEINFO
  110.   for (i=0; i<80; i++)
  111.     poke(screen_seg, i*2, 0x0720);
  112. #endif
  113. }
  114.  
  115. int ctrl_c_flag = 0;
  116.  
  117. ctrlbrk_func()
  118. {
  119. #if DEBUGGER
  120.   ctrl_c_flag = 1;
  121. #else
  122.   exit(3);
  123. #endif
  124. }
  125.  
  126. usage(char *s)
  127. {
  128.   printf("Usage: %s [program [options . . . ]]\n", s);
  129.   _exit(1);
  130. }
  131.  
  132. int have_80387;
  133. int use_xms=0;
  134. static word32 push32(void *ptr, int len);
  135.  
  136. main(int argc, char **argv, char **envp)
  137. {
  138.   int i, n, set_brk=0, emu_installed=0;
  139.   struct stat stbuf;
  140.   char *cp, *path, *argv0, *emu_fn=0;
  141.   unsigned short header[3];
  142.  
  143.   if (xms_installed())
  144.     use_xms = 1;
  145.   old_video_mode = peekb(0x40, 0x49);
  146.  
  147.   if (strcmp(argv[1], "!proxy") == 0)
  148.   {
  149.     int oseg, optr, i;
  150.     int far *oargv;
  151.     char far *oargve;
  152.     sscanf(argv[2], "%x", &argc);
  153.     sscanf(argv[3], "%x", &oseg);
  154.     sscanf(argv[4], "%x", &optr);
  155.     oargv = MK_FP(oseg, optr);
  156.     argv = (char **)malloc(sizeof(char *) * (argc+1));
  157.     for (i=0; i<argc+1; i++)
  158.     {
  159.       if (oargv[i] == 0)
  160.       {
  161.         argv[i] = 0;
  162.         break;
  163.       }
  164.       oargve = MK_FP(oseg, oargv[i]);
  165.       for (optr=0; oargve[optr]; optr++);
  166.       argv[i] = (char *)malloc(optr+1);
  167.       for (optr=0; oargve[optr]; optr++)
  168.         argv[i][optr] = oargve[optr];
  169.       argv[i][optr] = 0;
  170.     }
  171.   }
  172.  
  173.   ems_handle = emm_present();
  174.   switch (cputype())
  175.   {
  176.     case 1:
  177.       if ((ems_handle)&&(ems_handle != -1))
  178.     ems_free(ems_handle);
  179.       fprintf(stderr, "CPU must be a 386 to run this program.\n");
  180.       exit(1);
  181.     case 2:
  182.       if (ems_handle)
  183.     {
  184.     if (vcpi_installed = vcpi_present())
  185.       break;
  186.     else if (ems_handle != -1)
  187.       ems_free(ems_handle);
  188.     }
  189.       fprintf(stderr, "CPU must be in REAL mode (not V86 mode) to run this program.\n");
  190.       exit(1);
  191.   }
  192.  
  193.   if (peekb(0x40,0x49) == 7)
  194.     screen_seg = 0xb000;
  195.  
  196.   _fmode = O_BINARY;
  197.  
  198.   cp = getenv("GO32");
  199.   path = 0;
  200.   if (cp)
  201.     while (1)
  202.     {
  203.       char sw[100];
  204.       char val[100];
  205.       if (sscanf(cp, "%s%n", sw, &i) < 1)
  206.         break;
  207.       cp += i;
  208.       if (strcmp(sw, "ansi") == 0)
  209.         use_ansi = 1;
  210.       else if (strcmp(sw, "mono") == 0)
  211.         use_mono = 1;
  212.       else if (strcmp(sw, "2r1") == 0)
  213.         redir_2_1 = 1;
  214.       else if (strcmp(sw, "1r2") == 0)
  215.         redir_1_2 = 1;
  216.       else if (strcmp(sw, "2rm") == 0)
  217.         redir_2_mono = 1;
  218.       else if (strcmp(sw, "1rm") == 0)
  219.         redir_1_mono = 1;
  220.       else
  221.       {
  222.         val[0] = 0;
  223.         sscanf(cp, "%s%n", val, &i);
  224.         cp += i;
  225.         if (val[0] == 0)
  226.           break;
  227.       }
  228.       if (strcmp(sw, "driver") == 0)
  229.       {
  230.         if (path) free(path);
  231.         path = strdup(val);
  232.       }
  233.       else if (strcmp(sw, "tw") == 0)
  234.         gr_def_tw = atoi(val);
  235.       else if (strcmp(sw, "th") == 0)
  236.         gr_def_th = atoi(val);
  237.       else if (strcmp(sw, "gw") == 0)
  238.         gr_def_gw = atoi(val);
  239.       else if (strcmp(sw, "gh") == 0)
  240.         gr_def_gh = atoi(val);
  241.       else if (strcmp(sw, "emu") == 0)
  242.       {
  243.         if (emu_fn) free(emu_fn);
  244.         emu_fn = strdup(val);
  245.       }
  246.     }
  247. #if ! DEBUGGER
  248.   use_mono = 0;
  249. #endif
  250.   setup_graphics_driver(path);
  251.   if (path) free(path);
  252.   if (use_mono)
  253.   {
  254.     use_ansi = 0;
  255.     screen_seg = 0xb000;
  256.   }
  257.  
  258.   setbuf(stdin, 0);
  259.   atexit((atexit_t)exit_func);
  260.   ctrlbrk(ctrlbrk_func);
  261.   n = (int)ivec1-(int)ivec0;
  262.   for (i=0; i<256; i++)
  263.   {
  264.     idt[i].selector = g_rcode*8;
  265.     idt[i].stype = 0x8e00;
  266.     idt[i].offset0 = FP_OFF((int)ivec0+n*i);
  267.     idt[i].offset1 = 0;
  268.   }
  269.   idt[14].selector = g_ptss*8;
  270.   idt[14].stype = 0x8500;
  271.   idt[14].offset0 = 0;
  272.   idt[14].offset1 = 0;
  273.  
  274.   cp = getenv("387");
  275.   if (cp)
  276.     if (tolower(cp[0]) == 'n')
  277.       have_80387 = 0;
  278.     else if (tolower(cp[0]) == 'y')
  279.       have_80387 = 1;
  280.     else
  281.       have_80387 = detect_80387();
  282.   else
  283.     have_80387 = detect_80387();
  284.   if (have_80387)
  285.   {
  286.     idt[7].offset0 = (int)ivec7;
  287.     idt[7].offset1 = 0;
  288.     idt[0x75].offset0 = (int)ivec75;
  289.     idt[0x75].offset1 = 0;
  290.   }
  291.  
  292.   if (cp && (tolower(cp[0]) == 'q'))
  293.     if (have_80387)
  294.       printf("An 80387 has been detected.\n");
  295.     else
  296.       printf("No 80387 has been detected.\n");
  297.  
  298.   fillgdt(g_zero, 0, 0, 0, 0);
  299.   fillgdt(g_gdt, sizeof(gdt), ptr2linear(gdt), 0x92, 0);
  300.   fillgdt(g_idt, sizeof(idt), ptr2linear(idt), 0x92, 0);
  301.   fillgdt(g_rcode, 0xffff, (word32)_CS*16L, 0x9a, 0);
  302.   fillgdt(g_rdata, 0xffff, (word32)_DS*16L, 0x92, 0);
  303.   fillgdt(g_core, 0xffffffffL, 0, 0x92, 3);
  304.   fillgdt(g_acode, 0xefffffffL, 0x10000000L, 0x9a, 3);
  305.   fillgdt(g_adata, 0xefffffffL, 0x10000000L, 0x92, 3);
  306.   fillgdt(g_ctss, sizeof(TSS), ptr2linear(&c_tss), 0x89, 3);
  307.   fillgdt(g_atss, sizeof(TSS), ptr2linear(&a_tss), 0x89, 3);
  308.   fillgdt(g_ptss, sizeof(TSS), ptr2linear(&p_tss), 0x89, 3);
  309.   fillgdt(g_itss, sizeof(TSS), ptr2linear(&i_tss), 0x89, 3);
  310.   fillgdt(g_rc32, 0xffff, (word32)_CS*16L, 0x9a, 3);
  311.   fillgdt(g_grdr, 0xffff, (word32)gr_paging_segment*16L, 0x9a, 0);
  312.  
  313.   setup_tss(&c_tss, go_real_mode);
  314.   setup_tss(&a_tss, go_real_mode);
  315.   setup_tss(&o_tss, go_real_mode);
  316.   setup_tss(&f_tss, go_real_mode);
  317.   setup_tss(&i_tss, interrupt_common);
  318.   setup_tss(&p_tss, page_fault);
  319.   tss_ptr = &a_tss;
  320.  
  321.   argv0 = argv[0];
  322.   for (i=0; argv0[i]; i++)
  323.   {
  324.     if (argv0[i] == '\\')
  325.       argv0[i] = '/';
  326.     argv0[i] = tolower(argv0[i]);
  327.   }
  328.   if (strcmp(argv[1], "-nobrk") == 0)
  329.   {
  330.     set_brk=1;
  331.     argv++;
  332.     argc--;
  333.   }
  334.  
  335. #if TOPLINEINFO
  336.   for (i=0; i<80; i++)
  337.     poke(screen_seg, i*2, 0x0720);
  338. #endif
  339.  
  340.   self_contained = 0;
  341.   n = open(argv0, O_RDONLY|O_BINARY);
  342.   header[0] = 0;
  343.   read(n, header, sizeof(header));
  344.   if (header[0] == 0x5a4d)
  345.   {
  346.     header_offset = (long)header[1] + (long)header[2]*512L - 512L;
  347.     lseek(n, header_offset, 0);
  348.     header[0] = 0;
  349.     read(n, header, sizeof(header));
  350.     if (header[0] == 0x010b)
  351.       self_contained = 1;
  352.   }
  353.  
  354.   if (self_contained)
  355.   {
  356. #if DEBUGGER
  357.     debug_mode = 1;
  358. #else
  359.     debug_mode = 0;
  360. #endif
  361.     paging_set_file(argv0);
  362.     emu_installed = emu_install(emu_fn);
  363.     set_command_line(argv, envp);
  364. #if DEBUGGER
  365.     syms_init(argv0);
  366. #endif
  367.   }
  368.   else
  369.   {
  370.     header_offset = 0;
  371.     for (cp=argv0; *cp; cp++)
  372.       if (*cp == '.')
  373.         path = cp;
  374.     *path = 0;
  375.     if (stat(argv0, &stbuf)) /* not found */
  376.     {
  377.       fprintf(stderr, "%s.exe Copyright (C) 1991 DJ Delorie\n", argv0);
  378.       debug_mode = 1;
  379.       if (argv[1] == 0)
  380.         usage(argv0);
  381.       paging_set_file(argv[1]);
  382.       emu_installed = emu_install(emu_fn);
  383.       set_command_line(argv+1, envp);
  384. #if DEBUGGER
  385.       syms_init(argv[1]);
  386. #endif
  387.     }
  388.     else /* found */
  389.     {
  390.       debug_mode = 0;
  391.       paging_set_file(argv0);
  392.       emu_installed = emu_install(emu_fn);
  393.       set_command_line(argv, envp);
  394. #if DEBUGGER
  395.       syms_init(argv0);
  396. #endif
  397.     }
  398.   }
  399.  
  400.   if (set_brk)
  401.     paging_brk(0x8fffffffL);
  402.  
  403.   dalloc_init();
  404.   init_controllers();
  405.   if (emu_installed)
  406.   {
  407.     push32(&(a_tss.tss_eip), 4);
  408.     a_tss.tss_eip = 0xb0000020;
  409.   }
  410. #if DEBUGGER
  411.   debugger();
  412.   if (peekb(0x40, 0x49) != old_video_mode)
  413.   {
  414.     _AX = old_video_mode;
  415.     geninterrupt(0x10);
  416.   }
  417.   return 0;
  418. #else
  419.   go_til_stop();
  420.   if (tss_ptr->tss_irqn == 0x79)
  421.     fprintf(stderr, "Ctrl-C Hit!  Stopped at address %lx\n", tss_ptr->tss_eip);
  422.   else
  423.     fprintf(stderr, "Exception %d at eip=%lx\n", tss_ptr->tss_irqn, tss_ptr->tss_eip);
  424.   return 1;
  425. #endif
  426. }
  427.  
  428. #if !DEBUGGER
  429. gdtprint(i)
  430. {
  431.   printf("0x%02x: base=%02x%02x%04x lim=%02x%04x G=%d type=%02x\n",
  432.     i*8, gdt[i].base2, gdt[i].base1, gdt[i].base0,
  433.     gdt[i].lim1&0x0f, gdt[i].lim0, gdt[i].lim1>>6, gdt[i].stype);
  434. }
  435. #endif
  436.  
  437. static word32 push32(void *ptr, int len)
  438. {
  439.   if ((a_tss.tss_esp & ~0xFFF) != ((a_tss.tss_esp-len) & ~0xFFF))
  440.   {
  441.     a_tss.tss_cr2 = a_tss.tss_esp - len + ARENA;
  442.     page_in();
  443.   }
  444.   a_tss.tss_esp -= len;
  445.   a_tss.tss_esp = a_tss.tss_esp & (~3);
  446.   memput(a_tss.tss_esp+ARENA, ptr, len);
  447.   return a_tss.tss_esp;
  448. }
  449.  
  450. static foreach_arg(char **argv, int (*func)())
  451. {
  452.   int i;
  453.   FILE *f;
  454.   char buf[80];
  455.   for (i=0; argv[i]; i++)
  456.   {
  457.     if (argv[i][0] == '@')
  458.     {
  459.       f = fopen(argv[i]+1, "rt");
  460.       while (fscanf(f, "%s", buf) == 1)
  461.       {
  462.         if (strcmp(buf, "\032") != 0)
  463.           func(buf);
  464.       }
  465.       fclose(f);
  466.     }
  467.     else
  468.       func(argv[i]);
  469.   }
  470. }
  471.  
  472. static int num_actual_args;
  473.  
  474. static just_incr()
  475. {
  476.   num_actual_args++;
  477. }
  478.  
  479. static word32 *a;
  480.  
  481. pusharg(char *ar)
  482. {
  483.   a[num_actual_args] = push32(ar, strlen(ar)+1);
  484.   num_actual_args++;
  485. }
  486.  
  487. set_command_line(char **argv, char **envv)
  488. {
  489.   unsigned envc;
  490.   word32 *e, v, argp, envp;
  491.  
  492.   a_tss.tss_cr2 = a_tss.tss_esp + ARENA;
  493.   page_in();
  494.  
  495.   num_actual_args = 0;
  496.   foreach_arg(argv, just_incr);
  497.  
  498.   for (envc=0; envv[envc]; envc++);
  499.   e = (word32 *)malloc((envc+1)*sizeof(word32));
  500.   if (e == 0)
  501.   {
  502.     printf("Fatal! no memory to copy environment\n");
  503.     exit(1);
  504.   }
  505.   for (envc=0; envv[envc]; envc++)
  506.   {
  507.     v = push32(envv[envc], strlen(envv[envc])+1);
  508.     e[envc] = v;
  509.   }
  510.   e[envc] = 0;
  511.  
  512.   a = (word32 *)malloc((num_actual_args+1)*sizeof(word32));
  513.   if (a == 0)
  514.   {
  515.     printf("Fatal! no memory to copy arguments\n");
  516.     exit(1);
  517.   }
  518.   num_actual_args = 0;
  519.   foreach_arg(argv, pusharg);
  520.   a[num_actual_args] = 0;
  521.  
  522.   envp = push32(e, (envc+1)*sizeof(word32));
  523.   argp = push32(a, (num_actual_args+1)*sizeof(word32));
  524.  
  525.   push32(&envp, sizeof(word32));
  526.   push32(&argp, sizeof(word32));
  527.   v = num_actual_args;
  528.   push32(&v, sizeof(word32));
  529. }
  530.